/*
 * Somardas.java
 *
 * Created on 27 de abril de 2007, 0:04
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package futbol.tacticas.concursantes2007.AthleticSomardas;

import futbol.tacticas.concursantes.Tactica;

import java.awt.*;
import java.util.Vector;
import futbol.tacticas.*;
import futbol.General;
import futbol.tacticas.SituacionJugadores;

/**
 *
 * @author Pablike
 */
public class Somardas implements Tactica{
    
    private double bolax=0;//contienen la informacion sobre posicion, velocidad y
    private double bolay=0;//angulo de la bola en el turno anterior
    private double bolav=0;//para predecir su trayectoria
    private double bolaa=0;//
    
    //en nOponentes guardaremos las posiciones de los oponentes en el turno anterior 
    //para, con el desplazamiento en un turno poder calcular su velocidad
    private int nOponentes[][] = {
        {0,0,7},{0,0,7},{0,0,7},{0,0,7},{0,0,7},{0,0,7},{0,0,7},{0,0,7},
        {0,0,7},{0,0,7},{0,0,7}};
    private int timer =0;//almacenaremos el tiempo de juego
    
    private int nValores[][]={
        {-150,0,5},  // Jugador 1[0] Portero
        {-120,-30,6},  // Jugador 2[1] Central Izdo
        {-120,30,6},  // Jugador 3[2] Central Dcho
        {-40,0,7},  // Jugador 4[3] Pivote
        {-60,-85,5},  // Jugador 5[4] Carrilero Izdo
        {-60,85,5},  // Jugador 6[5] Carrilero Dcho
        {0,-40,6},  // Jugador 7[6] Volante Izdo
        {0,40,6},  // Jugador 8[7] Volante Dcho
        {60,-85,5},  // Jugador 9[8] Extremo Izdo
        {60,85,5},  // Jugador 10[9] Extremo Dcho
        {60,0,7}  // Jugador 11[10] Delantero
    };
    
    public Somardas() {
    }

    public Color getColor1() {return Color.BLACK;}
    public Color getColor2() {return Color.BLACK;}
    public Color getColorNumero() {return Color.WHITE;}
    public String getNombre() {return "Ath Somardas";}
    public int getXInicial(int n) {return nValores[n][0];}
    public int getYInicial(int n) {return nValores[n][1];}
    public int getFuerza(int n) {return nValores[n][2];}
    
    public double[] marcaje(Point jug,Point bola){
        //le pasamos la posicion del jugador a marcar y la bola
        //devuelve un vector con la posicion x e y a una distancia de 10
        //del jugador, en la trayectoria de la bola
        double ret[] = {0,0};
        double ang = General.getAngulo(jug.getX(),jug.getY(),bola.getX(),bola.getY());
        ret[0]=jug.getX()+10*Math.cos(ang);
        ret[1]=jug.getY()+10*Math.sin(ang);
        return ret;
    }
    
    public double[] Heuristica(SituacionJugadores sj,int num){
        //elegira a quien y donde ira el pase
        //la entrada es el jugador que hara el pase
        //y devolvera a quien pasamos (pos 0)
        //y la x e y donde le pasaremos (no le pasaremos a el directamente)
        //el mismo turno en que hacemos el pase el destino se movera hacia
        //donde tiene que recibir el pase
        double [] ret = {0,0,0};
        Point[] jug = sj.getMisJugadores();
        Point[] opo = sj.getContrario();
        Point bola = sj.getBola();
        double heuristica = 9999; //a menor heuristica mejor pase sera
        for (int destino =1;destino<11;destino++){
            if (destino!=num){//para evitar autopases
                for (double dang =0;dang<2*Math.PI;dang+=Math.PI/4){
                    //le pasaremos a una cierta distancia que veremos mas abajo
                    //a 8 posibles posiciones (intervalos de pi/4)
                    double x,y,turnos,dis2;
                    double vel = nValores[num][2]*3;
                
                    x=jug[destino].getX()+(10 - nValores[destino][2])*Math.cos(dang);
                    y=jug[destino].getY()+(10 - nValores[destino][2])*Math.sin(dang);
                    //la distancia a la que mandamos el pase es a la velocidad del jugador destino 
                    //(lo que puede recorrer en 1 turno)
                    //calculamos las x e y correspondientes
                    double dis = General.getDistancia(bola.getX(),bola.getY(),x,y);
                    turnos =0;dis2=0;
                    double ang = General.getAngulo(bola.getX(),bola.getY(),x,y);
                    for (double v = vel;v>0;v--){
                        double heur = 0;
                        turnos++;
                        double[] temp = mueveBola1Turno(x,y,ang,v);
                        x=temp[0];y=temp[1];ang=General.corregirAngulo(temp[2]);
                        if (v<15){ //si v>15 no se puede interceptar
                            double[] mio = getMasRapido(sj,x,y);
                            if (mio[1]<=turnos){
                                //Si algun jugador mio puede llegar a la bola
                                heur-=100;
                            }
                            mio = oponenteMasRapido(sj,x,y);
                            if (mio[1]<=turnos){
                                //si algun jugador oponente puede llegar a la bola
                                heur+=100;
                            }
                            heur-=v; //esto le da un poco de prioridad
                                     //a los pases cortos, es mucho menos probable
                                     //que me intercepten un pase si calculamos el 
                                     //destino con la bola a vel 14 que a vel 5
                            if (bola.getX()<jug[destino].getX()+(10 - nValores[destino][2])*Math.cos(dang)){
                                //esto favorece los pases hacia delante
                                heur-=100;
                            }
                        //AKI MAS POSIBLES VALORES PARA HEURISTICA
                            
                            if (destino==10){
                                //favorece los pases al delantero centro
                                heur-=50;
                                if (num==3){heur-=50;}
                                //mas aun si el que pasa es el volante, otro jugador de fuerza 7
                                //en una posicion ideal para pasarle a una buena velocidad
                                //saltandonos asi su mediocampo
                            }
                            if (destino==3){
                                //favorece los pases al volante para desahogar la defensa
                                heur-=100;
                            }
                            if (heur<heuristica){
                                heuristica = heur;
                                ret[0]=destino;
                                ret[1]=jug[destino].getX()+(10 - nValores[destino][2])*Math.cos(dang);
                                ret[2]=jug[destino].getY()+(10 - nValores[destino][2])*Math.sin(dang);
                            }
                        }
                    }
                }
            }
        }
        return ret;
    }
    
    public void calcularFuerzaContrarios(SituacionJugadores sj){
        //actualiza el valor de fuerza de los contrarios
        //dependiendo de la distanca recorrida el ultimo turno
        Point[] con =sj.getContrario();
        double x,y,xant,yant,dis;
        for (int n=0;n<11;n++){
            x=con[n].getX();y=con[n].getY();
            xant=nOponentes[n][0];yant=nOponentes[n][1];
            dis = General.getDistancia(xant,yant,x,y);
            if ((int)dis>(10-nOponentes[n][2])){
                nOponentes[n][2]=10-(int)dis;
            }
        }
    }
    
    public double posicionarPortero(SituacionJugadores sj){
        //nos posicionara el portero en la trayectoria de la bola
        Point bola=sj.getBola();
        if (bola.getX()==0 && bola.getY()==0) return 0;
        if (bola.getX()==bolax){
            return 0;
        }
        else{
            double a = (bola.getY()-bolay)/(bola.getX()-bolax);
            double b = bolay-(a*bolax); // Y = ax + b
            double y = a*(-150) +b;
            if (y>20) y=20;
            if (y<-20) y=-20;
            return y;
        }
    }
    
    public double[] mueveBola1Turno(double x1,double y1,double angulo,double velocidad){
        //le pasamos una posicion de la pelota, su velocidad y angulo
        //y nos devolvera  x,y,angulo al final de ese turno
        double ang = angulo;
        double velo = velocidad;
        double x = x1;
        double y = y1;
        double[] ret = {0,0,0};
        for (int n=0;n<velocidad;n++){
            x+=Math.cos(ang);
            y+=Math.sin(ang);
            if (x>160){
                x=320-x;  //160 - (x-160)
                ang=General.corregirAngulo(Math.PI-ang);
            }
            if (x<-160){
                x=-320-x; //-160 + (-160-x)
                ang=General.corregirAngulo(Math.PI-ang);
            }
            if (y>120){
                y=240-y; //120 - (x-120)
                ang=General.corregirAngulo(-ang);
            }
            if (y<-120){
                y=-240-y;  //-120 + (-120-x)
                ang=General.corregirAngulo(-ang);
            }
        }
        ret[0]=x;ret[1]=y;ret[2]=ang;
        return ret;
    }
    
    public double[] oponenteMasRapido(SituacionJugadores sj,double x,double y){
        //devolvera el oponente que mas rapido puede llegar a ese punto
        Point[] jug = sj.getContrario();
        Point bola=sj.getBola();
        double dist;
        double resul = 9999;
        double[] ret ={0,0};
        for (int i = 0;i<11;i++){
            dist = General.getDistancia(jug[i].getX(),jug[i].getY(),x,y);
            dist = dist / (10-nOponentes[i][2]);
            if (dist<resul){
                resul = dist;
                ret[0] = i;
                ret[1] = dist;
            }
        }
        return ret;
    }

    
    public double[] getMasRapido(SituacionJugadores sj,double x,double y){
        //devolvera el jugador que mas rapido puede llegar a ese punto, 
        Point[] jug = sj.getMisJugadores();
        Point bola=sj.getBola();
        double dist;
        double resul = 9999;
        double[] ret ={0,0};
        for (int i = 0;i<11;i++){
            dist = General.getDistancia(jug[i].getX(),jug[i].getY(),x,y);
            dist = dist / (10-nValores[i][2]);
            if (dist<resul){
                resul = dist;
                ret[0] = i;
                ret[1]=dist;
            }
        }
        return ret;
    }
    
    public double velocidadBola(SituacionJugadores sj){
        //hay que restarle uno para hacer calculos ya que la velocidad es
        //la del turno pasado
        Point bola=sj.getBola();
        if((bola.getX()==0)&&(bola.getY()==0)){return 0;}
        else{
            if((bola.getX()==bolax)&&(bola.getY()==bolay)){return 0;}
            else{return (General.getDistancia(bolax,bolay,bola.getX(),bola.getY())-1);}
        }
    }
    
    public double[] masCerca3(SituacionJugadores sj){
        //nos calcula que jugador puede llegar mas rapido a la bola, y 
        //adonde tendra que ir
        Point bola=sj.getBola();
        double [] ret = {0,0,0};
        if ((bola.getX()==bolax)&&(bola.getY()==bolay)){
            //si la bola esta quieta, devolvemos directamente el masrapido
            double[] temp = getMasRapido(sj,bola.getX(), bola.getY());
            ret[0] = temp[0];
            ret[1] =bola.getX();
            ret[2] =bola.getY();
        }
        else{
            //y si no calculamos donde estara la bola cuando sea bloqueable
            double velo = bolav;
            //en bolav hemos calculado la velocidad del turno anterior
            double x = bola.getX();
            double y = bola.getY();
            double [] sit ={0,0,0};
            double angulo = bolaa;
            double turnos =1;//turnos de demora, este turno seria 1
            //vamos al final del turno con velocidad 15 y no al del 14
            //ya que justo al final del 15 seria golpeable
            double dis = 0;
            if (velo>15){turnos = velo-14;}
            //en turnos los turnos que faltan para que sea golpeable la bola
            for (double n=0;n<turnos;n++){
                //movemos la bola hasta que sea golpeable
                sit=mueveBola1Turno(x,y,angulo,velo);
                x=sit[0];y=sit[1];
                angulo = sit[2];
                velo--;
            }
            double[] temp = getMasRapido(sj,x,y);
            ret[0]=temp[0];
            ret[1]=x;
            ret[2]=y;
        }
        return ret;
    }
    
    public int[] calcularAdelantados(SituacionJugadores sj){
        //devuelve los 4 jugadores mas adelantados del contarrio ordenados por la Y
        Point[] contrario = sj.getContrario();
        int ad1=0;int ad2=0;int ad3=0;int ad4=0;
        double xad1=200;double xad2=200;
        double xad3=200;double xad4=200;
        double tem =0;
        for (int t=0;t<11;t++){
            tem = contrario[t].getX();
            if (tem<xad1){
                xad4=xad3;xad3=xad2;xad2=xad1;
                ad4=ad3;ad3=ad2;ad2=ad1;
                xad1=tem;ad1=t;
            }
            else{
                if (tem<xad2){
                    xad4=xad3;xad3=xad2;
                    ad4=ad3;ad3=ad2;
                    xad2=tem;ad2=t;
                }
                else{
                    if (tem<xad3){
                        xad4=xad3;
                        ad4=ad3;
                        xad3=tem;ad3=t;
                    }
                    else{
                        if (tem<xad4){xad4=tem;ad4=t;}
                    }
                }
            }
        }//en ad1..ad4 tenemos sus jugadores mas adelantados
        //los ordenamos de menos a mas Y
        int temp =0;
        int y1,y2,y3,y4;
        y1=(int)contrario[ad1].getY();
        y2=(int)contrario[ad2].getY();
        y3=(int)contrario[ad3].getY();
        y4=(int)contrario[ad4].getY();
        if ((y2<=y1)&&(y2<=y3)&&(y2<=y4)){
            temp = ad2;ad2=ad1;ad1=temp;
            temp = y2;y2=y1;y1=temp;
        }
        else{
            if ((y3<=y1)&&(y3<=y2)&&(y3<=y4)){
                temp = ad3;ad3=ad1;ad1=temp;
                temp = y3;y3=y1;y1=temp;
            }
            else{
                if ((y4<=y1)&&(y4<=y3)&&(y4<=y2)){
                    temp = ad4;ad4=ad1;ad1=temp;
                    temp = y4;y4=y1;y1=temp;
                }
            }
        }
        if ((y3<=y4)&&(y3<=y2)){
            temp = ad3;ad3=ad2;ad2=temp;
            temp = y3;y3=y2;y2=temp;
        }
        else{
            if ((y4<=y2)&&(y4<=y3)){
                temp = ad4;ad4=ad2;ad2=temp;
                temp = y4;y4=y2;y2=temp;
            }
        }
        if ((y4<=y3)){
            temp = ad4;ad4=ad3;ad3=temp;
            temp = y4;y4=y3;y3=temp;
        }
        int[] ret = {ad1,ad2,ad3,ad4};
        return ret;
    }    
    
    public Vector<Comando> getComandos(SituacionJugadores sj) {
        Vector<Comando> com=new Vector();
        Point bola=sj.getBola();
        Point[] jug = sj.getMisJugadores();
        bolav=velocidadBola(sj);//calculamos la velocidad de la bola
        bolaa = General.getAngulo(bolax,bolay,bola.getX(),bola.getY());
            //y su angulo
        if ((timer!=0)&&(timer<11)){calcularFuerzaContrarios(sj);}
            //los 10 primeros turnos intentamos calcular la velocidad de
            //los contrarios (lo que se desplaza en 1 turno)
        //ahora habra que guardar las posiciones de los oponentes
        if (timer<11){
            for (int n=0;n<11;n++){
                nOponentes[n][0]=(int)sj.getContrario()[n].getX();
                nOponentes[n][1]=(int)sj.getContrario()[n].getY();
            }
        }
        timer++;
        
        //Posicionamiento PIVOTANDO
        //los jugadores de campo pivotaran de lado dependiendo de 
        //donde este la bola
        int a=(int)(bola.getY()/2);
        if (a<-30) a=-30;
        if (a>30) a=30;
        for (int n=1;n<11;n++){
            com.add(new ComandoIrA(n,nValores[n][0],nValores[n][1]+a));
        }
        
        //Movimiento portero
        com.add(new ComandoIrA(0,nValores[0][0], posicionarPortero(sj)));
        
        //Hacemos los marcajes
            Point[] contrario = sj.getContrario();
            int[] ade = calcularAdelantados(sj);
            double[] marca = marcaje(contrario[ade[0]],bola);
            com.add(new ComandoIrA(4,marca[0],marca[1]));
            marca = marcaje(contrario[ade[1]],bola);
            com.add(new ComandoIrA(1,marca[0],marca[1]));
            marca = marcaje(contrario[ade[2]],bola);
            com.add(new ComandoIrA(2,marca[0],marca[1]));
            marca = marcaje(contrario[ade[3]],bola);
            com.add(new ComandoIrA(5,marca[0],marca[1]));
                         
            //mas cercano
            double[] cercano = masCerca3(sj);
            com.add(new ComandoIrA((int)cercano[0],cercano[1], cercano[2]));
            
         //MODO ATAQUE calcula los pases
            double[] heu;
            Point[] co=sj.getContrario();
            Point[] ju=sj.getMisJugadores();
            
            for (int m =0;m<10;m++){
                if (General.getDistancia(bola.getX(),bola.getY(),ju[m].getX(),ju[m].getY())<10){
                    heu = Heuristica(sj,m);
                    com.add(new ComandoGolpearBola(m,heu[1],heu[2]));
                    com.add(new ComandoIrA((int)heu[0],heu[1], heu[2]));
                    
                    
                }
                
            }
            
            com.add(new ComandoTiroAPuerta(10,0));
        
        bolax=bola.getX();
        bolay=bola.getY();    
        return com;
    }
}
    
       
    
